﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//using System.Web;
using System.Net;
using System.Security;
using System.IO;

using QuickGraph;
using QuickGraph.Graphviz;
using QuickGraph.Graphviz.Dot;


namespace CrmWorkflowDependencies.Dependencies
{   
    public static class MyColor
    { 
        public static GraphvizColor LightBlue1 = new GraphvizColor(1, 200, 210, 230);
        public static GraphvizColor LightYellow1 = new GraphvizColor(1, 255, 230, 165);
        public static GraphvizColor Red1 = new GraphvizColor(1, 205, 25, 30);
        public static GraphvizColor LightRed1 = new GraphvizColor(1, 245, 120, 125);
    }

    public static class GraphExtensions
    {
        public static void SaveGraphiz(this IEdgeListGraph<Vertex, Edge<Vertex>> graph, string graphname)
        {
            FileInfo fi = new FileInfo(graphname);
            if (fi.Exists) fi.Delete();

            var graphviz = new GraphvizAlgorithm<Vertex, Edge<Vertex>>(graph);
            
            /// FORMAT
            //graphviz.GraphFormat.NodeSeparation = 1;
            graphviz.GraphFormat.IsConcentrated = true;

            graphviz.CommonVertexFormat.Shape = GraphvizVertexShape.Record;
            graphviz.CommonVertexFormat.Font = new GraphvizFont("Arial", 9);
            //graphviz.CommonVertexFormat.FillColor = new GraphvizColor(0, 155, 155, 155);
            //graphviz.CommonVertexFormat.Shape = GraphvizVertexShape.Record;
            //graphviz.CommonVertexFormat.Sides = 4;

            //graphviz.CommonEdgeFormat.MinLength = 2;

            /// FORMAT of Verticies
            graphviz.FormatVertex += new FormatVertexEventHandler<Vertex>(delegate(object sender, FormatVertexEventArgs<Vertex> e) {

                //System.Web.HttpUtility.UrlEncode(e.Vertex.Label);
                //e.VertexFormatter.Label = WebUtility.HtmlEncode(e.Vertex.Label);
                //e.VertexFormatter.Label = SecurityElement.Escape(e.Vertex.Label);

                //e.VertexFormatter.Label = e.Vertex.Label.ToUnicodeValue();                
                e.VertexFormatter.Label = e.Vertex.Label
                    .Replace("-", "_")
                    .Replace("\"", "'");

                if (e.Vertex is VertexProperty)
                {
                    /// приблизить, уменьшить (как свойство у класса)
                    e.VertexFormatter.Shape = GraphvizVertexShape.Plaintext;
                }

                //if (e.Vertex is HashtableVertex && ((HashtableVertex)e.Vertex).Components.Count > 1)
                //{
                //    e.VertexFormatter.Shape = GraphvizVertexShape.Record;
                //}

                //if (e.Vertex.Type == componenttype.Entity)
                //{
                //    e.VertexFormatter.Shape = GraphvizVertexShape.Record;
                //}

                if (e.Vertex.Type == componenttype.Workflow)
                {
                    e.VertexFormatter.FillColor = MyColor.LightBlue1;
                    e.VertexFormatter.Style = GraphvizVertexStyle.Filled;
                    e.VertexFormatter.Shape = GraphvizVertexShape.Rectangle;
                }

            });
            graphviz.FormatEdge += new FormatEdgeAction<Vertex, Edge<Vertex>>(delegate(object sender, FormatEdgeEventArgs<Vertex, Edge<Vertex>> e) {
                
                if (e.Edge.Source is VertexProperty || e.Edge.Target is VertexProperty)
                {
                    /// приблизить, уменьшить (как свойство у класса)
                    e.EdgeFormatter.MinLength = i++;
                    e.EdgeFormatter.Font = new GraphvizFont("Arial", 8);
                    e.EdgeFormatter.Style = GraphvizEdgeStyle.Dashed;
                    e.EdgeFormatter.Weight = 0.5;

                    e.EdgeFormatter.Dir = GraphvizEdgeDirection.Back;
                }

                if (e.Edge is MyEdge)
                {
                    e.EdgeFormatter.Weight = 0.5;

                    var mye = (MyEdge)e.Edge;
                    if (!string.IsNullOrEmpty(mye.PortFrom))
                    {
                        e.EdgeFormatter.TailPort = mye.PortFrom;
                    }
                    if (!string.IsNullOrEmpty(mye.PortTo))
                    {
                        e.EdgeFormatter.HeadPort = mye.PortTo;
                    }
                }

                if (e.Edge.Source.Type == componenttype.Workflow && e.Edge.Target.Type == componenttype.Workflow)
                {
                    e.EdgeFormatter.StrokeGraphvizColor = MyColor.Red1;
                }

            });

            graphviz.Generate(new FileDotEngine(), graphname);
        }

        static int i = 1;

        private static string ToUnicodeValue(this char c)
        {
            return string.Concat("&#", (int)c, ";");
        }

        private static string ToUnicodeValue(this string s)
        {
            return string.Join("", s.Select(c => c.ToUnicodeValue()).ToArray());
        }
    }
}